﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace libManagedMessageSystem
{
    unsafe public class MessageChannel
    {
        public MessageChannel(IntPtr pMessageChannel)
        {
            m_pMessageChannel = pMessageChannel;
            m_pHandler = null;
            m_ns = new NetStream();
        }

        public void Open(IMessageHandler h)
        {
            m_pHandler = h;

            libMessageSystemApi.OnLost ol = new libMessageSystemApi.OnLost(this.OnLost);
            m_h1 = GCHandle.Alloc(ol);
            libMessageSystemApi.OnMsg om = new libMessageSystemApi.OnMsg(this.OnMsg);
            m_h2 = GCHandle.Alloc(om);
            libMessageSystemApi.MessageChannelOpen(m_pMessageChannel, ol, om);

            MessageSystem.Channels.Add(this);
        }

        public bool Send(Message m, UInt16 nMessageId, UInt16 nDispatchId)
        {
            if(0==nMessageId)
            {
                return false;
            }
            else
            {
                MessageSystem.Ns.Reset();
                m.Write(MessageSystem.Ns);
                return libMessageSystemApi.MessageChannelSend(m_pMessageChannel, MessageSystem.Ns.DataPoint, MessageSystem.Ns.WriteLength, nMessageId, nDispatchId);
            }
        }

        public bool BroadCast(Message m, UInt16 nMessageId, UInt16[] nDispatchIds, UInt16 nDispatchCount)
        {
            MessageSystem.Ns.Reset();
            m.Write(MessageSystem.Ns);
            return libMessageSystemApi.MessageChannelBroadCast(m_pMessageChannel, MessageSystem.Ns.DataPoint, MessageSystem.Ns.WriteLength, nMessageId, nDispatchIds, nDispatchCount);
        }

        public bool Dispatch(UInt16 nDispatchId, UInt16 nMessageId, NetStream ns)
        {
            if(0==nMessageId)
            {
                return false;
            }
            else
            {
                return libMessageSystemApi.MessageChannelSend(m_pMessageChannel, ns.DataPoint, ns.DataLength, nMessageId, nDispatchId);
            }
        }

        public void Close()
        {
            libMessageSystemApi.MessageChannelClose(m_pMessageChannel);
        }

        private void OnLost(IntPtr mc)
        {
            MessageSystem.Channels.Remove(this);
            m_pHandler.OnLost();
            m_h1.Free();
            m_h2.Free();
        }

        private void OnMsg(IntPtr mc, byte* pBase, UInt32 length, UInt16 nDispatchId, UInt16 nMessageId)
        {
            m_ns.Reset(pBase, length);
            m_pHandler.OnMsg(this,nDispatchId,nMessageId,m_ns);
        }

        private IntPtr          m_pMessageChannel;
        private IMessageHandler m_pHandler;
        private NetStream       m_ns;
        private GCHandle        m_h1;
        private GCHandle        m_h2;
    }
}
